﻿using System;
using System.ComponentModel;
using System.Configuration;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using RG.Common.Configuration;
using RG.Common.WPF.BaseFrame;
using RG.Common.WPF.Commands;
using Microsoft.Practices.Unity;
using RG.Common;

namespace RG.Common.WPF.Filters
{
    [SupportDataBinding]
    public abstract class FilterBaseParamVM<T> : FilterBaseVM, INotifyPropertyChanged, IFirePropertyChanged
    {
        public delegate void ValueChangedDelegate();

        public event ValueChangedDelegate ValueChangedEvent;


        protected FilterBaseParamVM(IUnityContainer cfg)
            : base(cfg)
        {

        }


        protected void SetValueQuite(T newValue)
        {
            value = newValue;
        }

        protected abstract T ReturnDefaultEmptyValue();

        protected T value;
        [PropertySetting(SaveNullValue = true, SerializeAs = SettingsSerializeAs.Xml)]
        public T Value
        {
            get
            {
                if (!IsVisible || ValueEmpty())
                    return ReturnDefaultEmptyValue();
                return value;
            }
            set
            {
                this.value = value;
                ValueChanged();
                if (ValueChangedEvent != null)
                    ValueChangedEvent();
            }
        }
        [DependOn(new string[] { "Value" })]
        public bool IsFilled
        {
            get
            {
                return !ValueEmpty();
            }
        }



        protected virtual void ValueChanged()
        {
            OnPropertyChanged("FormattedValue");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


    public enum FilterVisibleMode
    {
        /// <summary>
        /// Развернут, когда выбран
        /// </summary>
        Авто = 0,
        /// <summary>
        /// Всегда развернут
        /// </summary>
        Развернут = 1,
        /// <summary>
        /// Невидимый
        /// </summary>
        Невидим = 2,
        /// <summary>
        /// Недоступен
        /// </summary>
        Недоступен = 3,
    }


    [SupportDataBinding]
    public abstract class FilterBaseVM
    {
        [DependOn("Settings")]
        public bool IsVisible
        {
            get
            {
                if (Settings == null)
                    return true;
                return Settings.Mode != FilterVisibleMode.Невидим && Settings.Mode != FilterVisibleMode.Недоступен;
            }
        }

        private FilterSettings settings;
        public FilterSettings Settings
        {
            get { return settings; }
            set
            {
                if(settings!=null)
                    settings.Unsubscribe();
                settings = value;
                settings.PropertyChanged += SettingsChanged;
            }
        }

        private void SettingsChanged(object sender, PropertyChangedEventArgs e)
        {
            Settings = Settings;
        }

        public IUnityContainer Cfg { get; set; }

        public IWorkplace Workplace { get; set; }

        public static readonly string EmptyText = "заполнить";

        public string Id { get; set; }

        public string Name { get; set; }

        protected FilterBaseVM(IUnityContainer cfg)
        {
            Cfg = cfg;
            Workplace = Cfg.Resolve<IWorkplace>();
            ClearCmd = new DelegateCommand(ClearValue);
            ClearQuietCmd = new DelegateCommand(DoClearQuiet);
            CollapseCmd = new DelegateCommand(DoCollapse);
            UncollapseCmd = new DelegateCommand(DoUncollapse);
            HideCmd = new DelegateCommand(DoHide);

        }

        private void DoHide()
        {
            Settings.Mode = FilterVisibleMode.Невидим;
        }

        private void DoUncollapse()
        {
            Settings.Mode = FilterVisibleMode.Развернут;
        }

        private void DoCollapse()
        {
            Settings.Mode = FilterVisibleMode.Авто;
            IsSelected = false;
        }

        private void DoClearQuiet()
        {
            ClearValueQuiet();
        }

        public virtual bool IsSelected { get; set; }

        public virtual void ClearValue()
        {
            if (Workplace.AskYesNo("Очистить фильтр?"))
                ClearValueQuiet();
        }

        public abstract void ClearValueQuiet();
        public virtual bool ValueEmpty()
        {
            return !IsVisible;
        }

        public ICommand ClearCmd { get; set; }
        public ICommand ClearQuietCmd { get; set; }
        public ICommand CollapseCmd { get; set; }
        public ICommand UncollapseCmd { get; set; }
        public ICommand HideCmd { get; set; }

        [DependOn("IsSelected", "Settings")]
        public ControlTemplate ViewTemplate
        {
            get
            {
                var resName = GetType().Name;
                if (GetType().IsGenericType)
                    resName = resName.Split('`')[0];

                if (
                    (Settings != null && Settings.Mode == FilterVisibleMode.Авто && IsSelected) ||
                    (Settings != null && Settings.Mode == FilterVisibleMode.Развернут) ||
                    IsSelected
                    )
                    resName = resName + "Selected";
                else
                {
                    if (resName.StartsWith("Filter") && !resName.Equals("FilterOldMultiStateFrameVM"))
                        resName = "FilterBaseVM";
                }
                var temp = Application.Current.Resources;

                var ret = (ControlTemplate)Application.Current.TryFindResource(resName);
                if (ret == null && GetType().BaseType != null)
                    ret = (ControlTemplate)Application.Current.TryFindResource(IsSelected ? GetType().BaseType.Name + "Selected" : GetType().BaseType.Name);//??
                return ret;
            }
        }
    }

    public class ValueChangedEventArgs<T> : EventArgs
    {
        public T NewValue { get; set; }
        public T OldValue { get; set; }
    }
}
